/**
 * 
 */
package de.androidbuch.amando.fotos;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;

/**
 * Der <code>FotoSpeicher</code> ist die Schnittstelle zu
 * auf dem Gerät erstellten Positionsfotos.
 * <p>
 * Der FotoSpeicher nutzt den Amando
 * <code>RoutenBilderProvider</code>. <br>
 * Er könnte auch in eine externe Anwendung kopiert werden.
 */
public final class FotoSpeicher {

  /** Markierung für Logging. */
  private static final String TAG = "FotoSpeicher";

  /**
   * Basis-URI für das FotoVerzeichnis.
   */
  public static final Uri FOTO_CONTENT_URI = Uri.parse(
      "content://" +
      "de.androidbuch.amando.fotoprovider" +
      "/fotos");

  /**
   * Titel := Eindeutiger Titel des Bildes. <br>
   * Pflichtfeld <br>
   * TEXT
   */
  public static final String FOTO_TITEL = "titel";

  /**
   * Stichwort der Geomarkierung der Position. Für jedes
   * Stichwort können mehrere Fotos gespeichert werden. <br>
   * Das Stichwort <em>kann</em>, muss aber nicht mit einem
   * Positionsstichwort eines Geokontakts übereinstimmen. 
   * <br>
   * Pflichtfeld <br>
   * TEXT
   */
  public static final String FOTO_STICHWORT_POS =
      "stichwortpos";

  /**
   * Name der Bilddatei. Wird i.A. vom System vergeben. <br>
   * Pflichtfeld <br>
   * TEXT
   */
  public static final String FOTO_DATEINAME = "_data";

  /**
   * Zeitpunkt der letzten Positionsmeldung. <br>
   * Pflichtfeld <br>
   * INTEGER
   */
  public static final String FOTO_ZEITSTEMPEL =
      "zeitstempel";

  /**
   * Der Speicher greift nur über statische Methoden zu.
   */
  private FotoSpeicher() {
  }

  /**
   * Liefert den Stream zum Lesen einer Fotodatei.
   * 
   * @param ctx
   *          Context der aufrufenden Anwendung.
   * @param fotoId
   *          Schlüssel des Foto-Datenbankeintrags.
   * @return Stream zum Lesen der Fotodatei. Null, wenn
   *         Datei nicht gefunden oder Zugriff nicht
   *         erlaubt.
   * @throws IOException
   *           falls Lesezugriff fehlschlägt.
   */
  public static InputStream ladeFoto(Context ctx,
      long fotoId)
      throws IOException {
    try {
      final Uri zielDateiUri = ContentUris.withAppendedId(
          FOTO_CONTENT_URI, fotoId);
      final ParcelFileDescriptor fotoDatei =
          ctx.getContentResolver().openFileDescriptor(
          zielDateiUri, "r");
      if (fotoDatei != null) {
        return new FileInputStream(fotoDatei
            .getFileDescriptor());
      }
    } catch (SecurityException zugriffVerweigert) {
      Log.e(TAG, zugriffVerweigert.getMessage());
      return null;
    }

    return null;
  }

  /**
   * Liefert einen Cursor auf alle Felder der
   * Metainformationen der Amando-Fotos. <br>
   * Es wird also quasi das "Verzeichnis" aller
   * Positionsfotos zurückgegeben.
   * 
   * @param ctx
   *          Context der aufrufenden Anwendung.
   * @return Cursor vor den Anfang der Ergebnismenge. Null,
   *         wenn der Provider nicht erreicht wurde.
   */
  public static Cursor ladeFotoListe(Context ctx) {
    try {
      final Cursor fotoListe = ctx.getContentResolver()
          .query(FOTO_CONTENT_URI, null, null, null, null);
      if (fotoListe == null) {
        Log.e(TAG,
            "Content Provider " + FOTO_CONTENT_URI +
            " nicht erreichbar.");
      }
      return fotoListe;
    } catch (SecurityException zugriffVerweigert) {
      Log.e(TAG, zugriffVerweigert.getMessage());
      return null;
    }
  }

  /**
   * Entfernt ein Foto aus der Datenbank.
   * 
   * @param ctx
   *          Context der aufrufenden Anwendung.
   * @param fotoId
   *          Schlüssel des Foto-Datenbankeintrags.
   * @return Anzahl der geloeschten Datensaetze.
   */
  public static int loescheFoto(Context ctx, long fotoId) {
    try {
      final Uri zielFotoUri =
          ContentUris
          .withAppendedId(FOTO_CONTENT_URI, fotoId);
      return ctx.getContentResolver().delete(
          zielFotoUri, null, null);
    } catch (SecurityException zugriffVerweigert) {
      Log.e(TAG, zugriffVerweigert.getMessage());
      return 0;
    }
  }

  /**
   * Speichert die Referenz zu einem Foto aus dem
   * Dateisystem in der Datenbank. <br>
   * Dabei wird auch der Zeitstempel für das Foto gesetzt. 
   * <br>
   * Existiert das Foto bereits in der Datenbank, so wird
   * ein weiterer Eintrag dazu angelegt.
   * <p>
   * Falls das Speichern nicht möglich ist, wird eine
   * SQLException ausgelöst.
   * <p>
   * Falls der Content Provider die Operation nicht erlaubt,
   * wird eine java.lang.SecurityException ausgelöst.
   * 
   * @param ctx
   *          Context der aufrufenden Anwendung.
   * @param titel
   *          Vom Anwender vergebener Titel des Fotos.
   * @param standort
   *          Stichwort zur Beschreibung des Standortes.
   * @param dateiName
   *          Dateiname auf der SD-Karte.
   * @return Datenbank-Id der Referenz auf das Foto.
   */
  public static long speichereFoto(Context ctx,
      String titel, String standort, String dateiName) {
    final ContentValues fotoDaten = new ContentValues();
    fotoDaten.put(FOTO_TITEL, titel);
    fotoDaten.put(FOTO_STICHWORT_POS, standort);
    fotoDaten.put(FOTO_DATEINAME, dateiName);
    fotoDaten.put(FOTO_ZEITSTEMPEL,
        System.currentTimeMillis());

    final Uri neuesFotoUri =
        ctx.getContentResolver().insert(
        FOTO_CONTENT_URI, fotoDaten);

    return Long.valueOf(
        neuesFotoUri.getPathSegments().get(1));
  }

}
